週刊Automatineマガジン 4.コンディションの更新


概要

UpdateでAutoの更新が行われるが、コンディションの更新もそこで行われる。

ただし、newを使ってAutoを切り替えるときは要注意、みたいな話。


ここでは、「コンディションはどうやって変化するのか」というのを解説する。


Automatineは各TackにTypeとValueという値のペアをセットすることができる。

実行中、「このフレーム内ならこういう状態」というのを表現することができるというわけ。


で、じゃあ次のタイミングの時、Autoの状態はそれぞれどうなってるの?っていう。

・Autoを初期化した時

・AutoをUpdateする前

・AutoをUpdateした後


初期化時

Autoには3つの初期化方法がある。


1.newを使って初期化する

auto = new Auto<I, U>(frame, IValue)


2.Autoクラスのinstance method ChangeToWithoutInheritConditions(Auto<I, U> newAuto)) を使う

auto = auto.ChangeToWithoutInheritConditions(new Auto<I, U>(frame, IValue))


3.Autoクラスのinstance method ChangeTo(Auto<I, U> newAuto)) を使う

auto = auto.ChangeTo(new Auto<I, U>(frame, IValue))



なぜ初期化に3つも方法があるのかというと、「直前のAutoの状態を引き継ぎたい」というケースがあるため。


1, 2の方法は、直前のAutoの状態の引き継ぎを行わず、

3だけは直前のAutoの状態の引き継ぎを行う。



ぶっちゃけると、


・最初のAutoを作り出す時はnew

・それ以降のAutoを変更したり更新したりするときにはChangeToメソッドを使う


というルールで覚えてもらって構わない。理由はこのページで後述する。



で、状態の話なんだけど、

初期化ずみのAutoは、特例として、実行前にもかかわらずConditionを返すことができる。


new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、無条件に0フレーム目のConditionを返す。


対として、

ChangeToメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、直前のAutoのConditionを返す。



この、メソッドによるautoの更新の特性の違いは、実際に使用する際にかなり顕著に出てくることになる。

具体的には、autoを更新する目的でnewやChangeToWithoutInheritConditionsメソッドを使うと、意図しない挙動を生みやすくなる。



Update前

Update前のAutoは、直前のUpdateで設定されたConditionを返す。


特に「初期化/更新したばかり」のAutoには特例があり、


new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、無条件に0フレーム目のConditionを返す。


対として、

ChangeToメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、直前のAutoのConditionを返す。



Update後

AutoのUpdateを行うと、そのタイミングに設定された動作を行う。

もし初めてのUpdateなら、ここで初めて、Auto自体にそのフレームでのConditionが付与されることになる。

ここに特例はない。

例えばその回でAutoの実行が完了する場合でも、最後のタイミングでセットされたConditionは正確に発現する。



初期化からUpdateにかけてのConditionを書くとこんな感じ


autoの初期化 or 更新から、Updateの流れを書き出してみると、次のような形になる。


(初期化/更新)

auto = new NewAuto<I, U>(0, IValue)


or


auto = auto.ChangeToWithoutInheritConditions(new NewAuto<I, U>(0, IValue))


or 


auto = auto.ChangeTo(new NewAuto<I, U>(0, IValue))


--- ---


(frame = 0)

// auto.Conditions()は0フレーム時の結果を返す(前のAutoのCondition or 新規Autoのデフォルト


Update(frame, UValue) (0フレームの適応をしてる


// auto.Conditions()は0フレーム時の結果を返す


frame++


--- ---


(frame = 1)

// auto.Conditions()は0フレーム時の結果を返す


Update(frame, UValue) (1フレームの適応をしてる


// auto.Conditions()は1フレーム時の結果を返す


frame++


--- ---


(frame = 2)

// auto.Conditions()は1フレーム時の結果を返す


Update(frame, UValue) (2フレームの適応をしてる


// auto.Conditions()は2フレーム時の結果を返す


frame++




注目すべきはframe = 0時のところで、


(frame = 0)

// auto.Conditions()は0フレーム時の結果を返す(前のAutoのCondition or 新規Autoのデフォルト


Update(frame, UValue) (0フレームの適応をしてる

0フレーム、autoの 初期化 か 更新 が終わってから一度もUpdateしていない状態でどんなConditionを返すのかが、

どの方法でautoの初期化をしたかで異なる。

new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、無条件に0フレーム目のConditionを返す。


対として、

ChangeToメソッドを使ってAutoを初期化/更新した場合、

実行前のAutoは、直前のAutoのConditionを返す。



あっこのコピペ3度目だ。


状態だけを見ていくと、違いがわかりやすい。



newかChangeToWithoutInheritConditionsを使った場合


auto = new Auto

auto = auto.ChangeToWithoutInheritConditions(new Auto)


--- ---

実行前のconditionは新Autoの0フレーム目

Update


実行後のconditionは新Autoの0フレーム目


ChangeToを使った場合


auto = auto.ChangeTo(new Auto)


--- ---

conditionは旧Autoの最後の状態


Update


実行後のconditionは新Autoの0フレーム目


太字部分の差が出る。


これは特に、autoの更新を行う際、

newやChangeToWithoutInheritConditionsを使うと

「うっかりUpdate前にConditionを取得して連続してないのが帰ってきて困る」みたいな問題を生みやすい。


なので、次のルールを鉄則にしておくといい。

・最初のAutoを作り出す時はnew

・それ以降のAutoを変更したり更新したりするときにはChangeToメソッドを使う


もちろん意図的に前のAutoのconditionを継がずに0フレーム目を出したい、というケース(猟奇的だ)に対応する場合、


単にnewで書くよりは、ChangeToWithoutInheritConditions という長ったらしいメソッドを使うと、より意図を鮮明にできると思うのでオススメ。